iT邦幫忙

2024 iThome 鐵人賽

DAY 11
0
AI/ ML & Data

AI 影像處理 30天系列 第 11

[AI 影像處理 30天] [Day 11] 定格瞬間:使用 OpenCV / FFmpeg 分割影片幀區

  • 分享至 

  • xImage
  •  

大家好!在前面的文章中,我們介紹了許多影像處理的技術,包括 2D 圖像置入、深度圖生成與應用、前後景分離等。今天,我們要將目光轉移到影片處理上,特別是「影片幀區分割」,也就是將影片中畫面變動較大的區段切分出來。透過自動化場景偵測,程式能在影片長度較長的情況下有效地分割幀區,取代人工一幀一幀判讀的繁瑣工作。如果你覺得概念較抽象,可以參考這個 影片 的 3:30 處,了解幀區分割的應用場景。

今天要介紹的是 Python 中兩種常見的影片幀區分割技術——OpenCVFFmpeg。我們將比較它們的優缺點,並結合實際測試結果來更深入理解其表現。

本次測試影片:Emma Watson Once Mistook Jimmy Fallon for Jimmy Kimmel


第一種:OpenCV

優點

  • 速度快,處理影片的效能不錯。
  • 可以偵測到影片中的細微變化,適合影片畫面變動頻繁的情境。

缺點

  • 需要手動調整幀區變化的閾值,設定過高或過低都可能影響偵測效果。

程式碼範例:

import datetime
import cv2

def main():
    cap = cv2.VideoCapture('../test_video.mp4')
    ret, prev_frame = cap.read()
    prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
    threshold = 750000
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    output_filename_template = 'segment_{}.mp4'
    segment_index = 0

    def start_new_writer(frame, segment_index):
        height, width, _ = frame.shape
        filename = output_filename_template.format(segment_index)
        return cv2.VideoWriter(filename, fourcc, 30, (width, height))

    out = start_new_writer(prev_frame, segment_index)

    while True:
        ret, curr_frame = cap.read()
        if not ret:
            break

        curr_gray = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)
        diff = cv2.absdiff(prev_gray, curr_gray)
        non_zero_count = cv2.countNonZero(diff)

        if non_zero_count > threshold:
            segment_index += 1
            out.release()
            out = start_new_writer(curr_frame, segment_index)

        out.write(curr_frame)
        prev_gray = curr_gray

    cap.release()
    out.release()

if __name__ == '__main__':
    start_time = datetime.datetime.now()
    main()
    end_time = datetime.datetime.now()
    print('Time taken:', end_time - start_time)

切分效果 (共切出 60 個片段):

image.png


第二種:FFmpeg (從 PySceneDetect 調用)

優點

  • 處理速度較快:經實驗測試,FFmpeg 比 OpenCV 快約 1.9 倍,具高效能。
  • 切割準確度高:在偵測畫面變化的精準度上,FFmpeg 表現優異。

缺點

  • 淡入效果問題:如果影片開頭有淡入效果,使用預設參數可能無法偵測到開場畫面,需調整偵測參數如 adaptive_thresholdmin_content_val 才能達到理想效果。
  • 參數調整需求高:雖然速度較快,但需要針對影片內容調整參數,才能達到最佳偵測效果。

程式碼範例:

import os
from scenedetect import detect, split_video_ffmpeg
from scenedetect.detectors import AdaptiveDetector
from datetime import datetime

def split_video_by_ffmpeg(movie_path, output_dir, adaptive_threshold, min_content_val):
    start_time = datetime.now()
    scene_list = detect(movie_path, AdaptiveDetector(adaptive_threshold=adaptive_threshold, min_content_val=min_content_val))
    split_video_ffmpeg(movie_path, scene_list, output_dir=output_dir)
    end_time = datetime.now()
    print(f"Total time taken: {end_time - start_time} seconds")
    return len(scene_list)

def main():
    movie_path = "/renhe's code/test_video.mp4"
    output_dir = "/renhe's code/benchmarks/emma/"
    adaptive_threshold_values = [1.5, 2.0, 2.5, 3.0, 3.5]
    min_content_val_values = [5.0, 10.0, 15.0, 20.0, 25.0]

    for adaptive_threshold in adaptive_threshold_values:
        for min_content_val in min_content_val_values:
            test_output_dir = os.path.join(output_dir, f"{adaptive_threshold}_{min_content_val}")
            os.mkdir(test_output_dir)
            split_video_by_ffmpeg(movie_path, test_output_dir, adaptive_threshold, min_content_val)

if __name__ == "__main__":
    main()

切分效果 (參數使用預設值,共切出 18 個片段):

image.png

其他參數分析

frame_block.png

圖 1: Total Frame Blocks vs. Min Content Value
此圖展示了隨著 min_content_val 變化,總幀區塊數的變化情況。結果表明,較低的 adaptive_threshold 可以捕捉到更多的場景變化。

time_frame_rel.png

圖 2: Total Time Taken vs. Min Content Value
總耗時隨著 min_content_val 增加而減少,特別在較低的 adaptive_threshold 下更明顯。

time_taken.png

圖 3: Total Time Taken vs. Total Frame Blocks
顯示了總幀區塊數與總耗時的正相關性,隨著幀區塊數增加,耗時也隨之增加。


OpenCV與FFmpeg方案實際效能比較

我們針對兩種方法進行了效能測試,結果如下:

  1. 速度比較:FFmpeg 的處理速度比 OpenCV 快 1.903 倍。實驗結果顯示,OpenCV 完成影片分割花費了約 45 秒,而 FFmpeg 則僅需 23 秒。
  2. 偵測準確性:OpenCV 能夠偵測到影片中細微的變化,特別是在影片開頭部分。FFmpeg 雖然速度較快,但若使用預設參數,對於有淡入效果的影片開頭偵測較弱,需要額外調整 adaptive_thresholdmin_content_val 才能提升效果。
  3. 整體偵測能力:兩者都能夠偵測到影片開場的畫面變化,根據影片的具體需求進行參數調整是關鍵。

如何選擇適合的方案?

  • 追求速度:如果你的影片處理需要高效,建議優先選擇 FFmpeg。
  • 精準度優先:對於偵測影片細微變化的需求,OpenCV 的表現更穩定,但可能需要手動調整參數。
  • 淡入問題解決方案:若影片開頭有淡入效果且使用 FFmpeg,請調整 adaptive_thresholdmin_content_val 參數,以提升偵測準確度。

總結

今天我們比較了 OpenCV 和 FFmpeg 這兩種常見的影片幀區分割技術。根據具體需求選擇適合的方法,並根據影片特性調整參數,可以顯著提升處理效率與準確度。


撰文者: Winston


上一篇
[AI 影像處理 30天] [Day 10] 追蹤焦點:YOLO V8 物件軌跡追蹤技術
下一篇
[AI 影像處理 30天] [Day 12] ASR 語音任務:WhisperX
系列文
AI 影像處理 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言